package cn.itsource.ymcc.service.impl;

import cn.itsource.ymcc.client.ESFeignClient;
import cn.itsource.ymcc.client.MediaFeignClient;
import cn.itsource.ymcc.constant.CourseConstants;
import cn.itsource.ymcc.constant.RConst;
import cn.itsource.ymcc.domain.*;
import cn.itsource.ymcc.dto.PaySuccessDto;
import cn.itsource.ymcc.mapper.*;
import cn.itsource.ymcc.result.JsonResult;
import cn.itsource.ymcc.service.ICourseService;
import cn.itsource.ymcc.util.AssertUtil;
import cn.itsource.ymcc.vo.CourseEditVo;
import cn.itsource.ymcc.vo.CourseParamVo;
import cn.itsource.ymcc.vo.CourseVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.aspectj.weaver.ast.Var;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zongchangjiang
 * @since 2023-03-31
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private TeacherMapper teacherMapper;
    @Autowired
    private CourseDetailMapper courseDetailMapper;
    @Autowired
    private CourseMarketMapper courseMarketMapper;
    @Autowired
    private CourseResourceMapper courseResourceMapper;
    @Autowired
    private CourseSummaryMapper summaryMapper;
    @Autowired
    private CourseTypeMapper courseTypeMapper;
    @Autowired
    private ESFeignClient courseFeignClient;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private CourseChapterMapper courseChapterMapper;
    @Autowired
    private MediaFeignClient mediaFeignClient;
    @Autowired
    private CourseUserLearnMapper courseUserLearnMapper;


    @GlobalTransactional
    @Override
    public void add(CourseVo courseVo, JSONObject currentUser) {
        //主表搞定
        CourseParamVo course1 = courseVo.getCourse();
        Course course = new Course();
        BeanUtils.copyProperties(course1,course);
        course.setStatus(RConst.Num.INT_0);//课程状态，下线：0 ， 上线：1
        course.setLoginId(currentUser.getLong("id"));
        course.setLoginUserName(currentUser.getString("username"));
        List<Long> teacharIds = courseVo.getTeacharIds();
        List<Teacher> teachers = teacherMapper.selectBatchIds(teacharIds);
        String teacherNames = teachers.stream()
                .map(Teacher::getName)
                .collect(Collectors.joining(","));
        course.setTeacherNames(teacherNames);//根据 courseVo.getTeacharIds() 去查询老师的名字
        baseMapper.insert(course);
        //详情
        CourseDetail courseDetail = courseVo.getCourseDetail();
        courseDetail.setId(course.getId());
        courseDetailMapper.insert(courseDetail);
        //营销
        CourseMarket courseMarket = courseVo.getCourseMarket();
        courseMarket.setId(course.getId());
        courseMarketMapper.insert(courseMarket);
        //资源 压缩包
        CourseResource courseResource = courseVo.getCourseResource();
        courseResource.setCourseId(course.getId());
        courseResourceMapper.insert(courseResource);
        //中间表  课程与老师的表
        baseMapper.insertCourseTeacher(course.getId(),teacharIds);

        //情况记录
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        courseSummary.setCommentCount(RConst.Num.INT_0);
        courseSummary.setSaleCount(RConst.Num.INT_0);
        courseSummary.setViewCount(RConst.Num.INT_0);
        summaryMapper.insert(courseSummary);

    }

    @Override
    public void edit(CourseVo courseVo) {
        System.out.println(courseVo);
        //主表  修改
        CourseParamVo course = courseVo.getCourse();
        Course DBcourse = baseMapper.selectById(course.getId());
        BeanUtils.copyProperties(course,DBcourse);
        //老师名字的修改
        List<Long> teacharIds = courseVo.getTeacharIds();
        List<Teacher> teachers = teacherMapper.selectBatchIds(teacharIds);
        String teacherNames = teachers.stream()
                .map(Teacher::getName)
                .collect(Collectors.joining(","));
        DBcourse.setTeacherNames(teacherNames);//根据 courseVo.getTeacharIds() 去查询老师的名字
        baseMapper.updateById(DBcourse);
        //详情  删除添加
        courseDetailMapper.deleteById(course.getId());
        CourseDetail courseDetail = courseVo.getCourseDetail();
        courseDetail.setId(course.getId());
        courseDetailMapper.insert(courseDetail);
        //营销  删除添加
        courseMarketMapper.deleteById(course.getId());
        CourseMarket courseMarket = courseVo.getCourseMarket();
        courseMarket.setId(course.getId());
        courseMarketMapper.insert(courseMarket);
        //中间表  删除添加
        baseMapper.deleteByCourseId(course.getId());
        baseMapper.insertCourseTeacher(course.getId(),teacharIds);
        //资源   修改
        CourseResource courseResource = courseVo.getCourseResource();

        //只有一个
        CourseResource resource = courseResourceMapper.selectOne(new QueryWrapper<CourseResource>()
                .eq("course_id", course.getId()));
        resource.setResources(courseResource.getResources());
        courseResourceMapper.updateById(resource);
    }

    @Override
    public CourseEditVo findAllDataById(Long id) {
        CourseEditVo courseEditVo = new CourseEditVo();
        //1.查询课程详情信息
        courseEditVo.setCourseDetail(courseDetailMapper.selectById(id));

        //2.查询课程市场营销信息
        courseEditVo.setCourseMarket(courseMarketMapper.selectById(id));

        //3.查询课件资源
        CourseResource resource = courseResourceMapper.selectOne(
                new QueryWrapper<CourseResource>()
                .eq("course_id", id));
        courseEditVo.setCourseResource(resource);

        //4.查询课程的讲师id集合  查询t_course_teacher中间表
        List<Long> teacherIds = baseMapper.selectTeacherIdsByCourseId(id);
        courseEditVo.setTeacharIds(teacherIds);

        //5.连表查询当前课程的课程类别，获取它的path字段
        Course course = baseMapper.selectById(id);
        CourseType courseType = courseTypeMapper.selectById(course.getCourseTypeId());
        courseEditVo.setCourseTypePath(courseType.getPath());
        return courseEditVo;
    }

    @GlobalTransactional
    @Override
    public void onLineCourse(List<Long> ids) {
        //1.判断  ids 有没有东西
        AssertUtil.isFalse(ids.isEmpty(),"老铁，你不选中数据，臣妾上不了啊....");
        //2.查询(保证数据库对的)数据库  看是不是有上线的
        List<Course> courses = baseMapper.selectCourseByStatusAndIds(ids, RConst.Num.INT_1);//既可以查询线上 也可以查询线下的
        // 方案   如果找到一个就直接报错
        AssertUtil.isTrue(courses.isEmpty(),"已选中的数据已存在上线的请重新选择");
        // 方案二  把已经上线的过滤  (用户体验好) 你们去实现
        //3.修改状态 保存数据库
        baseMapper.onLineOrOffLineCourse(ids,RConst.Num.INT_1);
        //4.往es里面添加数据  --- 查询 直接添加
        //赋值
        ids.forEach(id->{
            CourseDoc courseDoc = getCourseDoc(id);
            courseFeignClient.saveCourse(courseDoc);

            //5.消息推送 为了钱 (如果有人关注了当前课程  我们是不是通知他  短信 邮箱 站内信 )  场景
            //必须使用异步 多线程  定时器  redis mq
            //事务消息  单向() 同步  异步
            //惊喜惊喜，期待已久的课程 java大神班 发布了,<a href='http://www.itsource.cn?courseId=7'>点我</a>快速尝鲜。
            //短信
            MessageSms messageSms = new MessageSms();
            messageSms.setContent("惊喜惊喜，期待已久的课程 "+courseDoc.getName());
            //查询数据库找当前课程关注人
            messageSms.setPhone("13388888888");
            messageSms.setUserId(-1L);
            messageSms.setTitle(courseDoc.getName());
            String sms = JSON.toJSONString(messageSms);
            rocketMQTemplate.sendOneWay(CourseConstants.TOPIC_COURSE_MESSAGE_SMS+":"+CourseConstants.TAGS_COURSE_MESSAGE_SMS,
                    sms);
            //邮箱 发送
            //站内信
        });

    }

    /**
     * 课程详情页面：加载课程数据、课程详情、课程市场营销、课程统计信息、课程的讲师集合、课程的章节  =》 (建议)Vo或者HashMap
     *  课程数据、课程详情、课程市场营销、课程统计信息：这四个数据可以从数据库中查询，（建议 性能好）也可以从索引库中查询
     *  课程的章节=》树形结构
     * @param courseId
     * @return
     */
    @Override
    public Map<String, Object> detailData(Long courseId) {
        JsonResult courseDocResult = courseFeignClient.findCourseDocByCourseId(courseId);
        AssertUtil.isNotNull(courseDocResult.getData(),"获取课程详情失败!");
        CourseDoc courseDoc = JSON.parseObject(courseDocResult.getData().toString(), CourseDoc.class);
        //直接把 courseDoc 丢给前端吗？ 可以直接丢 也可以才分(相对来说)
        //课程数据
        Course course = new Course();
        BeanUtils.copyProperties(courseDoc,course);
        course.setStartTime(new Date(courseDoc.getStartTime()));
        course.setEndTime(new Date(courseDoc.getEndTime()));
        course.setOnlineTime(new Date(courseDoc.getOnlineTime()));
        course.setStatus(1);

        //课程详情
        CourseDetail courseDetail = new CourseDetail();
        BeanUtils.copyProperties(courseDoc,courseDetail);
        //课程市场营销
        CourseMarket courseMarket = new CourseMarket();
        BeanUtils.copyProperties(courseDoc,courseMarket);
        courseMarket.setPrice(new BigDecimal(courseDoc.getPrice()));
        courseMarket.setPriceOld(new BigDecimal(courseDoc.getPriceOld()));
        //课程统计信息
        CourseSummary courseSummary = new CourseSummary();
        BeanUtils.copyProperties(courseDoc,courseSummary);

        //查询课程的讲师集合
        List<Teacher> teacherList = baseMapper.selectTeacherByCourseId(courseId);
        //查询课程的章节
        List<CourseChapter> courseChapters = courseChapterMapper.selectList(
                new QueryWrapper<CourseChapter>().eq("course_id", courseId));
        //查询视频
        JsonResult mediaFileByCourseId = mediaFeignClient.findMediaFileByCourseId(courseId);
        //查询回来的视频
        List<JSONObject> list = JSON.parseObject(mediaFileByCourseId.getData().toString(), List.class);

        //封装一棵树
        Map<Long, CourseChapter> chapterMap = new HashMap<>();
        courseChapters.forEach(c -> chapterMap.put(c.getId(),c));
        for (JSONObject o : list) {
            MediaFile mediaFile = JSON.parseObject(o.toString(), MediaFile.class);
            //获取当前视频的章节
            CourseChapter courseChapter = chapterMap.get(mediaFile.getChapterId());
            courseChapter.getMediaFiles().add(mediaFile);
        }

        Map<String,Object> result = new HashMap<>();
        result.put("course",course);
        result.put("courseMarket",courseMarket);
        result.put("courseDetail",courseDetail);
        result.put("courseSummary",courseSummary);
        result.put("teachers",teacherList);
        result.put("courseChapters",chapterMap);
        return result;
    }

    @GlobalTransactional
    @Override
    public void handlePaySuccess(PaySuccessDto paySuccessDto) {
        //销量+1
        List<Long> courseId = paySuccessDto.getCourseId();

//        summaryMapper.updateSumById(1L,0,0,58464);
        //学习的是经验
        List<CourseSummary> summaryList = summaryMapper.selectList(new QueryWrapper<CourseSummary>().in("id", courseId));
        summaryList.forEach(summary ->{
//            summary.setSaleCount(summary.getSaleCount()+1);
//            summaryMapper.updateById(summary);
            summaryMapper.updateSumById(summary.getId(),1,0,0);
            //给用户添加购买数据
            CourseUserLearn courseUserLearn = new CourseUserLearn();
            courseUserLearn.setCourseId(summary.getId());
            courseUserLearn.setCourseOrderNo(paySuccessDto.getOrderNo());
            courseUserLearn.setStartTime(new Date());
            Long time= System.currentTimeMillis()+(1000*60*60*24*356);
            courseUserLearn.setEndTime(new Date(time));
            courseUserLearn.setLoginId(paySuccessDto.getUserId());
            courseUserLearn.setState(RConst.Num.INT_0);
            courseUserLearn.setCreateTime(new Date());
            courseUserLearnMapper.insert(courseUserLearn);
        });
    }

    /**
     * 构建CourseDoc
     * @param id
     * @return
     */
    private CourseDoc getCourseDoc(Long id){
        CourseDoc courseDoc = new CourseDoc();
        //查询主表课程
        Course course = baseMapper.selectById(id);
        // 将相同字段和相同类型 并且要有setget
        BeanUtils.copyProperties(course,courseDoc);
        //courseTypeName
        CourseType courseType = courseTypeMapper.selectById(course.getCourseTypeId());
        courseDoc.setCourseTypeName(courseType.getName());
        //startTime
        courseDoc.setStartTime(course.getStartTime().getTime());
        //endTime
        courseDoc.setEndTime(course.getEndTime().getTime());
        //onlineTime
        courseDoc.setOnlineTime(course.getOnlineTime().getTime());

        //详情表
        CourseDetail courseDetail = courseDetailMapper.selectById(course.getId());
        BeanUtils.copyProperties(courseDetail,courseDoc);
        //收费规则
        CourseMarket courseMarket = courseMarketMapper.selectById(course.getId());
        BeanUtils.copyProperties(courseMarket,courseDoc);
        //price
        courseDoc.setPrice(courseMarket.getPrice().doubleValue());
        //priceOld
        courseDoc.setPriceOld(courseMarket.getPriceOld().doubleValue());
        //销量
        CourseSummary courseSummary = summaryMapper.selectById(course.getId());
        BeanUtils.copyProperties(courseSummary,courseDoc);
        //收藏  t_course_collect  安装逻辑来说要去查询数据
        courseDoc.setCollectCount(0);
        return courseDoc;
    }
}
